package view;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import model.Model;
import model.interactionHandlerInitializer.InteractionHandlerInitializer;
import model.interactionhandler.InteractionContainer;

public class InteractionOverlay extends Overlay{

	private final int buttonWidth = 100;
	private final int buttonHeight = 30;
	private final int spacing = 10;
	private final int noInteractionWidth = 300;
	private final int noInteractionHeight = 30;
	private final int noInteractionStringYSpacing = 20;
	private final int noInteractionStringXSpacing = 45;
	
	private InteractionContainer ic;
	private BufferedImage img;
	private boolean interactionActive;
	private Map<InteractionHandlerInitializer, MouseListener> listeners;
	
	
	
	public InteractionOverlay( Dimension size, InteractionContainer ic ) {
		super(size);
		this.ic = ic;
		interactionActive = false;
		this.listeners = new HashMap<InteractionHandlerInitializer, MouseListener>();
		this.ic.register( this );
	}
	
	public void update ( Model m ) {
		if( m != ic ) { return ; }
		if( ic.isInteracting() ) {
			this.updateSubscribers();
			this.forceRedraw();
			interactionActive = true;
		} else{ //it is not interacting
			interactionActive = false;
			super.removeAllButtons();
			this.forceRedraw();
		}
	}
	
	public void escapeInteractionScreen() {
		interactionActive = false;
		this.removeAllButtons();
		this.forceRedraw();
	}
	
	public void drawOverlay( Graphics g ) {
		if( !interactionActive ) { return ; }
		if( isBuffered() ) {
			g.drawImage( img, 0, 0, null );
		}//if it is not buffered, create the image and saved it to the buffer
		super.removeAllButtons();//make sure there are no buttons from before
		img = new BufferedImage(super.getOuterDimension().width,
				super.getOuterDimension().height, BufferedImage.TYPE_INT_ARGB );
		Graphics g2 = img.getGraphics();
			if( hasInteractions() ) {
			addButtons();//add buttons to super class
			Point p1 = getUpperLeftOfLeftMostButton( ic.getInteractions() );
			Point p2 = this.getDownRighttOfRightMosttButton( ic.getInteractions() );
			g2.fillRect( p1.x - spacing, p1.y - spacing, (p2.x + spacing) - (p1.x - spacing),
					(p2.y + spacing) - (p1.y - spacing));
		} else {//if it doesn't have interactions, then just display an esc message
			Dimension d = this.getOuterDimension();
			g2.fillRect( (d.width/2) - noInteractionWidth/2 , (d.height/2) - noInteractionHeight/2,
					noInteractionWidth, noInteractionHeight);
			Color c = g2.getColor();
			g2.setColor( Color.BLACK );
			g2.drawString( "No interactions. Press ESC to exit.", (d.width/2) - noInteractionWidth/2 + noInteractionStringXSpacing,
					(d.height/2) - noInteractionHeight/2 + noInteractionStringYSpacing);
			g2.setColor(c);
		}
		g.drawImage( img, 0, 0, null );
	}
	
	public void onResize() {
		this.forceRedraw();
	}
	
	public void setListeners(Map<InteractionHandlerInitializer, MouseListener> listeners ) {
		this.listeners = listeners;
	}
	
	public void clearListeners() {
		this.listeners.clear();
	}
	
	public void addListener( InteractionHandlerInitializer init, MouseListener l ) {
		this.listeners.put( init, l );
	}
	
	private MouseListener getMouseListener( InteractionHandlerInitializer init ) {
		return this.listeners.get( init );
	}
	
	private void addButtons() {
		List<InteractionHandlerInitializer> l = ic.getInteractions();
		if( l == null ) { return ; }
		Point upperLeft = getUpperLeftOfLeftMostButton( l );
		for( InteractionHandlerInitializer init : l ) {
			GameButton b = new GameButton( init.getName(), new Rectangle(upperLeft.x, 
					upperLeft.y, buttonWidth, buttonHeight), ModelToImage.getImage(init.getName()) );
			b.attachListener( this.getMouseListener( init ) );
			super.addButton( b );
		}
	}
	
	
	private boolean hasInteractions() {
		List<InteractionHandlerInitializer> l = ic.getInteractions();
		return ( l != null ) && ( l.size() > 0 );
	}
	
	private Point getUpperLeftOfLeftMostButton( List<InteractionHandlerInitializer> l ) {
		return new Point( super.getOuterDimension().width/2 - sizeOfButtonsBlock(l)/2,
				super.getOuterDimension().height/2 - buttonHeight/2);
	}
	
	private Point getDownRighttOfRightMosttButton( List<InteractionHandlerInitializer> l ) {
		return new Point( super.getOuterDimension().width/2 + sizeOfButtonsBlock(l)/2,
				super.getOuterDimension().height/2 + buttonHeight/2);
	}
	
	/**
	 * Returns the width of button box (from the left of the upper left most button, to the right
	 * of the right most button).  
	 */
	private int sizeOfButtonsBlock( List<InteractionHandlerInitializer> l ) {
		if (l == null ) { return 0; }
		int count = l.size();
		return ( (count) * buttonWidth) + ( (count - 1) * spacing );
	}
	
	private boolean isBuffered() {
		return !(img == null);
	}
	
	private  void forceRedraw() {
		img = null;
	}
}
